

<!DOCTYPE html>
<html lang="zh" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/walker_sue/img/favicon.png">
  <link rel="icon" type="image/png" href="/walker_sue/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="">
  <meta name="author" content="lk">
  <meta name="keywords" content="">
  <title>淘宝定向广告演化和天池天猫复购预测 - Walker_Sue</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/walker_sue/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/github-gist.min.css" />
    
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/walker_sue/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/walker_sue/js/utils.js" ></script>
  <script  src="/walker_sue/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.3.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/walker_sue/">&nbsp;<strong>Walker</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/">
                <i class="iconfont icon-home-fill"></i>
                主页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                文档
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/">
                    
                    主题博客
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/guide/">
                    
                    配置指南
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/icon/">
                    
                    图标用法
                  </a>
                
              </div>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" href="javascript:">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('/walker_sue/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container page-header text-center fade-in-up">
    <span class="h2" id="subtitle">
    
</span>




<div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-02-26 15:53" pubdate>
        February 26, 2021 pm
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      5.9k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      72
       分钟
    </span>
  

  
  
</div>


</div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto" id="post">
            <!-- SEO header -->
            <h1 style="display: none">淘宝定向广告演化和天池天猫复购预测</h1>
            
            <div class="markdown-body" id="post-body">
              <div align='center' ><font size='10'>机器学习-BI</font></div>

<hr>
<div align='center' ><font size='5'>Week_05</font></div>
<div align='center' ><font size='5'>淘宝定向广告演化和天池天猫复购预测</font></div>

<hr>
<h2 id="一、淘宝定向广告演化"><a href="#一、淘宝定向广告演化" class="headerlink" title="一、淘宝定向广告演化"></a>一、淘宝定向广告演化</h2><p>推荐系统的主要挑战之一，是同时解决Memorization和Generalization。Memorization根据历史行为数据，推荐通常和用户已有行为的物品直接相关的物品。而Generalization会学习新的特征组合，提高推荐物品的多样性。 DeepFM 中 Wide &amp; Deep 分别对应 Memorization &amp; Generalization。<br></p>
<p><strong>Memorization:</strong> 面对拥有大规模离散sparse特征的CTR预估问题时，将特征进行非线性转换，然后再使用线性模型是在业界非常普遍的做法，最流行的即「LR+特征叉乘」。Memorization 通过一系列人工的特征叉乘（cross-product）来构造这些非线性特征，捕捉sparse特征之间的高阶相关性，即 “记忆” 历史数据中曾共同出现过的特征对。<br><br>典型代表是LR模型，使用大量的原始sparse特征和叉乘特征作为输入，很多原始的dense特征通常也会被分桶离散化构造为sparse特征。这种做法的优点是模型可解释高，实现快速高效，特征重要度易于分析，在工业界已被证明是很有效的。<br><br>Memorization的缺点是：</p>
<ul>
<li>需要更多的人工设计；</li>
<li>可能出现过拟合。可以这样理解：如果将所有特征叉乘起来，那么几乎相当于纯粹记住每个训练样本，这个极端情况是最细粒度的叉乘，我们可以通过构造更粗粒度的特征叉乘来增强泛化性；</li>
<li>无法捕捉训练数据中未曾出现过的特征对。例如上面的例子中，如果每个专业的人都没有下载过《消愁》，那么这两个特征共同出现的频次是0，模型训练后的对应权重也将是0；</li>
</ul>
<p><strong>Generalization:</strong><br>Generalization 为sparse特征学习低维的dense embeddings 来捕获特征相关性，学习到的embeddings 本身带有一定的语义信息。可以联想到NLP中的词向量，不同词的词向量有相关性，因此Generalization是基于相关性之间的传递。这类模型的代表是DNN和FM。<br><br>Generalization的优点是更少的人工参与，对历史上没有出现的特征组合有更好的泛化性 。在推荐系统中，当user-item matrix非常稀疏时，例如有和独特爱好的users以及很小众的items，NN很难为users和items学习到有效的embedding。这种情况下，大部分user-item应该是没有关联的，但dense embedding 的方法还是可以得到对所有 user-item pair 的非零预测，因此导致 over-generalize并推荐不怎么相关的物品。此时Memorization就展示了优势，它可以“记住”这些特殊的特征组合。 <br></p>
<h3 id="1-baseline模型"><a href="#1-baseline模型" class="headerlink" title="1.baseline模型"></a>1.baseline模型</h3><p>1.1 LR模型（线性模型） <br><br>LR模型 + 人工特征，LR模型不能处理非线性特征，所以需要特征工程去加入非线性特征 <br><br>1.2 MLR模型（非线性模型） <br><br>Mixed Logistic Regression，混合逻辑回归， <br><br>采用分而治之的策略，用分段线性+级联，拟合高维空间的非线性分类面，相比于人工来说提升了效率和精度 <br><br><a target="_blank" rel="noopener" href="https://arxiv.org/abs/1704.05194v1">https://arxiv.org/abs/1704.05194v1</a> <br></p>
<h3 id="2-DNN模型"><a href="#2-DNN模型" class="headerlink" title="2.DNN模型"></a>2.DNN模型</h3><p>DNN模型大多遵从 Embedding + MLP这一基础网络架构，即将原始高维的不同的离散特征映射为固定长度的低维embedding向量，并将embedding向量作为多个全连接层的输入，拟合高阶的非线性关系，最后通过Sigmoid等手段将输出值归一到0~1，表示点击概率。相比于传统的LR、GBDT、FM等模型，这类DNN的模型能减少大量的人工构造特征过程，并且能学习特征之间的非线性关系。<br><br>通常流程是:Sparse Features -&gt; Embedding Vector -&gt; pooling layer -&gt; MLPs -&gt; Sigmoid -&gt; Output  <br><br><strong>2.1 工作机制</strong><br>下图的 Base Model, 是现有的大多数 CTR 模型采用的模式: <br><br><img src="DNN.png" srcset="/walker_sue/img/loading.gif"><br><br><br>红蓝粉三色节点分别表示商品 ID （Goods ID）, 店铺 ID （Shop ID）, 类目 ID （Cate ID） 三种稀疏特征, 其他的输入特征, 使用白色节点表示 （比如左边的用户特征, 比如用户 ID; 还有右边的上下文特征, 比如广告位之类的特征）. 注意 Goods 1 ~ Goods N 用来描述用户的历史行为. 候选广告 Candidate Ad 本身也是商品, 也具有 Goods / Shop / Cate ID 三种特征. <br><br>自底向上观测 Base Model 的工作机制：<br></p>
<ul>
<li>第一模块：特征表示。<ul>
<li>可将特征大致分为四类：user profile、user behavior、ad 以及 context 部分。</li>
<li>告设为目标。</li>
<li>类特征包含多个field，用户信息包含性别、年龄等等；用户行为包含用户访问过的物品编号；广告包含广告id，商店id等；上下文包含设计类型id，时间等等。</li>
<li>特征可以被编码成one-hot表示，例如女性可以被编码成[0,1]。有的特征可以进行 multi-hot 编码，与 one-hot 编码不同，multi-hot 编码中，一个向量可能存在多个 1。</li>
<li>TR序列模型中，值得注意的是每个字段都包含一个行为列表，每个行为对应一个one-hot向量。</li>
</ul>
</li>
<li>第二模块：嵌入层。<ul>
<li>学习特征的低维向量表示，将维数较大的稀疏特征矩阵转换成低维稠密特征矩阵。</li>
<li>每一个field都有一个独立的 embedding matrix。</li>
<li>值得注意的是，由于每个用户的历史行为数据各不相同，因此 e 的列数是不确定的。相应地也就不能直接与其他field的嵌入向量首尾相接 作为MLP层的输入。</li>
</ul>
</li>
<li>第三模块：pooling层。<ul>
<li>由于不同的用户有不同个数的行为数据，导致embedding矩阵的向量大小不一致，而全连接层只能处理固定维度的数据，因此利用Pooling Layer得到一个固定长度的向量。</li>
<li>本层对 e 进行sum pooling，即将一个类别的embedding向量输入进池化操作，转化为一个固定长度的向量，解决维度不定的问题。</li>
</ul>
</li>
<li>第四模块：链接层。<ul>
<li>经过embedding layer和pooling layer后，原始稀疏特征被转换成多个固定长度的用户兴趣的抽象表示向量。</li>
<li>然后利用concat layer聚合抽象表示向量，输出该用户兴趣的唯一抽象表示向量；作为 MLP 层的输入 。</li>
</ul>
</li>
<li>第五模块：MLP 层，将concat layer输出的抽象表示向量作为MLP的输入，自动学习数据之间的高阶交叉特征。<ul>
<li>损失函数 ：基于深度学习的CTR模型广泛使用的损失函数是 负对数似然函数（the negative log-likelihood function）Loglos，使用标签作为目标项来监督整体的预测。</li>
</ul>
</li>
</ul>
<p><strong>2.2 模型特点</strong><br><br><strong>优点：</strong></p>
<ul>
<li>神经网络可以拟合高阶的非线性关系, 同时减少了人工特征的工作量。<br><br><strong>缺点：</strong></li>
<li>表示用户的兴趣多样性有限制 （这是最大的瓶颈） 。在对用户历史行为数据进行处理时, 每个用户的历史点击个数是不相等的, 包含了许多兴趣信息，如何对用户多种多样的兴趣建模？我们要把它们编码成一个固定长的向量（这个向量就是用户表示，是用户兴趣的代表），需要做pooling （sum or average）, 会损失信息。比如：<ul>
<li>K维向量，最多只能表达K个独立的兴趣，而用户的兴趣可能不止K；</li>
<li>K的大小会对计算量产生明显影响，一般用大的K效果会更好，即扩展向量的维度，但这样会增加学习的参数和在有限的数据中有过拟合的风险；</li>
</ul>
</li>
<li>没有考虑用户与广告之间的关系。在电子商务领域中，用户的历史行为数据（User Behavior Data）中包含大量的用户兴趣信息，之前的研究并没有针对Behavior data特殊的结构（Diversity + Local Activation）进行建模。比如 对于同一个用户, 如果候选广告 （Candidate Ad） 发生了变化, 用户的兴趣却依然是同一个向量来表达, 显然这限制了模型的表达能力, 毕竟用户的兴趣是丰富的/变化的。</li>
<li>忽略隐式特征的挖掘和表示。DNN模型直接将用户的行为视作用户的兴趣。行为是兴趣的载体，能反映兴趣，但若直接用行为表示兴趣则略有不妥。因为，行为是序列化产生的，如果像大部分现有的模型那样直接采用行为即兴趣的做法，会忽略行为之间的依赖关系。此外，当前时刻的兴趣往往直接导致了下一行为的发生。</li>
<li>忽略兴趣的变化。如之前所讲，用户的兴趣是不断变化的。例如用户对衣服的喜好，会随季节、时尚风潮以及个人品味的变化而变化，呈现一种连续的变迁趋势。但在淘宝平台中，用户的兴趣是丰富多样的，且每个兴趣的演变基本互不影响。此外，影响最终行为的仅仅是与目标商品相关的兴趣。</li>
<li>不必将某个用户所有的兴趣【用户的历史购买记录】全部压缩到向量中，因为只有用户部分的兴趣会影响当前行为（对候选广告点击或不点击）。例如，一位女游泳运动员会点击推荐的护目镜，这主要是由于购买了泳衣而不是上周购物清单中的鞋子。<br>

</li>
</ul>
<h3 id="3-DIN模型"><a href="#3-DIN模型" class="headerlink" title="3.DIN模型"></a>3.DIN模型</h3><p>针对DNN模型的问题，阿里提出了DIN模型。其核心思想：用户的兴趣是多元化的（diversity），并且对于特定的广告，用户不同的兴趣会产生不同的影响（local activation）。DIN同时对Diversity和Local Activation进行建模。<br><br>DIN 不会通过使用同一向量来表达所有用户的不同兴趣，而是通过考虑历史行为的相关性来自适应地计算用户兴趣的表示向量（对于给定的广告）。 该表示向量随不同广告而变化。DIN 通过考虑【给定的候选广告】和【用户的历史行为】的相关性，来计算用户兴趣的表示向量。具体来说就是通过引入局部激活单元，通过软搜索历史行为的相关部分来关注相关的用户兴趣，并采用加权和来获得有关候选广告的用户兴趣的表示。与候选广告相关性较高的行为会获得较高的激活权重，并支配着用户兴趣。该表示向量在不同广告上有所不同，大大提高了模型的表达能力。<br></p>
<p><strong>4.1 创新</strong> <br><br>Deep Interest NetWork有以下几点创新： <br></p>
<ul>
<li>针对Diversity： 针对用户广泛的兴趣，DIN用an interest distribution去表示，即用 Pooling（weighted sum）对Diversity建模（对用户多种多样的兴趣建模）。</li>
<li>针对Local Activation：<ul>
<li>DNN 直接求sum或average损失了很多信息。所以 DIN 稍加改进，利用attention机制实现 Local Activation，从用户历史行为中动态学习用户兴趣的embedding向量，针对不同的广告构造不同的用户抽象表示，从而实现了在数据维度一定的情况下，更精准地捕捉用户当前的兴趣。</li>
<li>对用户历史行为进行了不同的加权处理，针对不同的广告，不同的 behavior id 赋予不同的权重，这个权重是由当前behavior id和候选广告共同决定的，这就是Attention机制。即针对当前候选Ad，去局部的激活（Local Activate）相关的历史兴趣信息。</li>
<li>与当前候选Ad相关性越高的历史行为，会获得越高的attention score，从而会主导这一次预测。</li>
</ul>
</li>
<li>CTR中特征稀疏而且维度高，通常利用L1、L2、Dropout等手段防止过拟合。由于传统L2正则计算的是全部参数，CTR预估场景的模型参数往往数以亿计。DIN提出了一种正则化方法，在每次小批量迭代中，给与不同频次的特征不同的正则权重；</li>
<li>由于传统的激活函数，如Relu在输入小于0时输出为0，将导致许多网络节点的迭代速度变慢。PRelu虽然加快了迭代速度，但是其分割点默认为0，实际上分割点应该由数据决定。因此，DIN提出了一种数据动态自适应激活函数Dice。</li>
<li>针对大规模稀疏数据的模型训练：当DNN深度比较深（参数非常多），输入又非常稀疏的时候，很容易过拟合。DIN提出Adaptive regularizaion来防止过拟合，效果显著。<br></li>
</ul>
<p><strong>4.2 架构</strong> <br><br>DIN架构图如下：<br><br><img src="DIN01.png" srcset="/walker_sue/img/loading.gif"></p>
<p>DIN同时对Diversity和Local Activation进行建模，具体体现如下图: <br><br><img src="DIN02.png" srcset="/walker_sue/img/loading.gif"></p>
<br>

<p><strong>4.3 改进</strong> <br><br>4.3.1 添加Attention机制 <br></p>
<ul>
<li>在对用户行为的embedding计算上引入了attention network (也称为Activation Unit) </li>
<li>把用户历史行为特征进行embedding操作，视为对用户兴趣的表示，之后通过Attention Unit，对每个兴趣表示赋予不同的权值</li>
<li>Attention Weight是由用户历史行为和候选广告进行匹配计算得到的，对应着洞察（用户兴趣的Diversity，以及Local Activation）</li>
<li>对Activation Weight采用了较内积而言稍复杂的外积+PRelu+MLP的简单模型<br>

</li>
</ul>
<p>4.3.2 评价指标的改进<br></p>
<ul>
<li>AUC改进<ul>
<li>改进AUC，不是将所有用户的正负样本在一起计算，而是对于每个用户单独计算自身的AUC，并根据其自身的行为数量（如点击）进行加权处理<br></li>
<li>$$AUC = \frac{\sum^n_{i=1} W_i*{AUC}<em>i}{\sum^n</em>{i=1} W_i} = \frac{\sum^n_{i=1} impression_i*{AUC}<em>i}{\sum^n</em>{i=1} impression_i}$$  <br></li>
<li>计算了用户级别的AUC，按展示次数进行加权，消除了用户偏差对模型评价的影响，更准确地描述了模型对于每个用户的表现效果</li>
</ul>
</li>
<li>评价指标RelaImpr<ul>
<li>$$RelaImpr = (\frac{AUC(measured model) - 0.5}{AUC(baseline model) - 0.5} - 1)*100%$$</li>
<li>RelaImpr代表相对于based model的相对改进指标，对于随机猜测的话，值AUC是0.5 <br></li>
<li><img src="DIN03.png" srcset="/walker_sue/img/loading.gif"></li>
</ul>
</li>
<li>激活函数Dice<ul>
<li>Dice是PReLU的一种泛化形式，根据输入数据分布的不同，自适应变化。</li>
<li><img src="DIN04.png" srcset="/walker_sue/img/loading.gif"></li>
</ul>
</li>
<li>使用L2正则<ul>
<li>在淘宝中有很多商品，大约有6亿ID，Embedding layer参数量巨大，直接使用L2 norm计算量过大，每一步迭代都需要更新所有参数</li>
<li>MBA-Reg将L2-norm 推广到样本层面，每一步迭代只计算样本相关参数<br>

</li>
</ul>
</li>
</ul>
<h3 id="4-DIEN模型"><a href="#4-DIEN模型" class="headerlink" title="4.DIEN模型"></a>4.DIEN模型</h3><p>4.1 创新 <br></p>
<ul>
<li>兴趣提取器层（interest extractor layer）：首先DIEN选择GRU来建模两行为之间的依赖性。其次由于隐藏状态缺乏对兴趣表示的监督，作者提出了辅助损失，即使用下一个行为来监督当前隐藏状态的学习。作者把这些有额外监督的隐藏状态称为【兴趣状态】，有助于捕获更多的语义意义用于兴趣表示，推动GRU的隐藏状态，从而有效地表示兴趣</li>
<li>兴趣演化层（interest evolving layer）：兴趣的多样性会导致兴趣偏移的现象。在相邻的访问中，用户的意图可能非常不同，用户的一个行为可能依赖于很久以前的行为。因此，作者提出建立与目标物相关的兴趣演化轨迹模型，设计了带有注意力机制更新门的GRU—AUGRU。运用兴趣状态和目标物体去计算相关性。AUGRU增强了在兴趣演化中相关兴趣的影响，同时削弱了兴趣漂移所产生的非相关兴趣效应。通过在更新门中引入注意机制，AUGRU可以实现针对不同目标物体的特定兴趣演化过程。</li>
</ul>
<p>4.2 模型结构 <br></p>
<ul>
<li>具体模型结构如下：<br><br><img src="DIEN01.png" srcset="/walker_sue/img/loading.gif"></li>
<li>通过引入序列模型 AUGRU 模拟了用户兴趣进化的过程</li>
<li>在 Embedding layer 和 Concatenate layer 之间加入了生成兴趣的 Interest Extractor Layer 和模拟兴趣演化的 Interest Evolving layer</li>
<li>Interest Extractor Layer 使用了GRU的结构抽取了每一个时间片内用户的兴趣</li>
<li>Interest Evolving layer 利用序列模型 AUGRU 的结构将不同时间的用户兴趣串联起来，形成兴趣进化的链条</li>
<li>最终把当前时刻的“兴趣向量”输入上层的多层全连接网络，与其他特征一起进行最终的 CTR 预估</li>
</ul>
<h3 id="5-DSIN模型"><a href="#5-DSIN模型" class="headerlink" title="5.DSIN模型"></a>5.DSIN模型</h3><p>模型流程如下：<br></p>
<ul>
<li>首先使用带有Bias Encoding（偏置编码）的Self-Attention（自我注意力）机制 =&gt; 提取用户的Session兴趣向量</li>
<li>然后利用Bi-LSTM 对用户的Session之间的交互进行建模 =&gt; 带有上下文信息的Session兴趣向量</li>
<li>最后利用Activation Unit（局部激活单元）自适应地学习各种会话兴趣对目标item的影响<br><img src="DSIN01.png" srcset="/walker_sue/img/loading.gif"><br><img src="DSIN02.png" srcset="/walker_sue/img/loading.gif"></li>
</ul>
<h3 id="6-淘宝定向广告演化总结"><a href="#6-淘宝定向广告演化总结" class="headerlink" title="6.淘宝定向广告演化总结"></a>6.淘宝定向广告演化总结</h3><ul>
<li>降低信息损失</li>
<li>先有洞察，再有拟合</li>
<li>模型是为了更好的拟合洞察</li>
<li>工程中提出Dice，Mini-Batch Aware Regularization，auxiliary loss</li>
<li>随着模型越来越复杂，越需要并行计算（GPU）<br><img src="ad.png" srcset="/walker_sue/img/loading.gif"></li>
</ul>
<br>


<h3 id="二、天池天猫用户复购预测"><a href="#二、天池天猫用户复购预测" class="headerlink" title="二、天池天猫用户复购预测"></a>二、天池天猫用户复购预测</h3><ul>
<li>Challenge背景：<ul>
<li><a target="_blank" rel="noopener" href="https://tianchi.aliyun.com/competition/entrance/231576/information">https://tianchi.aliyun.com/competition/entrance/231576/information</a></li>
<li>电商经常会做大促，比如打折或者发放优惠券，尤其是在特殊的节日，比如黑色星期五，双十一等，目的是为了吸引大量的新用户。然而，许多吸引过来的购买者只是一次性交易，这些促销对于转换为长期的顾客来说可能收效甚微</li>
<li>为了解决这个问题，对于复购用户的预测就尤为重要，因为关注潜在的忠诚消费者，对于商家来说可以降低促销成本，增加投资回报率ROI</li>
<li>在线广告领域，客户定位是非常有挑战的，尤其是对于新购买者来说。但是对于天猫来说，已经积累了大量用户行为日志，可以解决这个问题</li>
</ul>
</li>
<li>Challenge目标：<ul>
<li>提供了双十一促销期间的商家和新用户数据，目标是对于给定的商家，预测新用户是否能成为忠诚用户，即未来6个月内会购买这个商家的商品</li>
</ul>
</li>
<li>数据格式：<ul>
<li>双十一以及前6个月的数据，label标签表明了用户是否为重复购买者</li>
</ul>
</li>
</ul>
<p>代码实现: <br></p>
<pre><code class="hljs python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># 加载数据</span>
<span class="hljs-comment"># 用户行为，使用format1进行加载</span>
user_log = pd.read_csv(<span class="hljs-string">&#x27;../data_format1/user_log_format1.csv&#x27;</span>, dtype=&#123;<span class="hljs-string">&#x27;time_stamp&#x27;</span>:<span class="hljs-string">&#x27;str&#x27;</span>&#125;)
user_info = pd.read_csv(<span class="hljs-string">&#x27;../data_format1/user_info_format1.csv&#x27;</span>)
train_data1 = pd.read_csv(<span class="hljs-string">&#x27;../data_format1/train_format1.csv&#x27;</span>)
submission = pd.read_csv(<span class="hljs-string">&#x27;../data_format1/test_format1.csv&#x27;</span>)
train_data = pd.read_csv(<span class="hljs-string">&#x27;../data_format2/train_format2.csv&#x27;</span>)
train_data1[<span class="hljs-string">&#x27;origin&#x27;</span>] = <span class="hljs-string">&#x27;train&#x27;</span>
submission[<span class="hljs-string">&#x27;origin&#x27;</span>] = <span class="hljs-string">&#x27;test&#x27;</span>
matrix = pd.concat([train_data1, submission], ignore_index=<span class="hljs-literal">True</span>, sort=<span class="hljs-literal">False</span>)
print(matrix)
matrix.drop([<span class="hljs-string">&#x27;prob&#x27;</span>], axis=<span class="hljs-number">1</span>, inplace=<span class="hljs-literal">True</span>)
<span class="hljs-comment">#01 </span>
<span class="hljs-comment"># 连接user_info表，通过user_id关联</span>
matrix = matrix.merge(user_info, on=<span class="hljs-string">&#x27;user_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)
<span class="hljs-comment"># 使用merchant_id（原列名seller_id）</span>
user_log.rename(columns=&#123;<span class="hljs-string">&#x27;seller_id&#x27;</span>:<span class="hljs-string">&#x27;merchant_id&#x27;</span>&#125;, inplace=<span class="hljs-literal">True</span>)
<span class="hljs-comment"># 格式化</span>
user_log[<span class="hljs-string">&#x27;user_id&#x27;</span>] = user_log[<span class="hljs-string">&#x27;user_id&#x27;</span>].astype(<span class="hljs-string">&#x27;int32&#x27;</span>)
user_log[<span class="hljs-string">&#x27;time_stamp&#x27;</span>] = pd.to_datetime(user_log[<span class="hljs-string">&#x27;time_stamp&#x27;</span>], <span class="hljs-built_in">format</span>=<span class="hljs-string">&#x27;%H%M&#x27;</span>)
<span class="hljs-comment"># 缺失值填充</span>
user_log[<span class="hljs-string">&#x27;brand_id&#x27;</span>].fillna(<span class="hljs-number">0</span>, inplace=<span class="hljs-literal">True</span>)
matrix[<span class="hljs-string">&#x27;age_range&#x27;</span>].fillna(<span class="hljs-number">0</span>, inplace=<span class="hljs-literal">True</span>)
matrix[<span class="hljs-string">&#x27;gender&#x27;</span>].fillna(<span class="hljs-number">2</span>, inplace=<span class="hljs-literal">True</span>)
<span class="hljs-comment"># 02</span>
<span class="hljs-comment"># User特征处理</span>
groups = user_log.groupby([<span class="hljs-string">&#x27;user_id&#x27;</span>])
<span class="hljs-comment"># 用户交互行为数量 u1</span>
temp = groups.size().reset_index().rename(columns=&#123;<span class="hljs-number">0</span>:<span class="hljs-string">&#x27;u1&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=<span class="hljs-string">&#x27;user_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)
<span class="hljs-comment"># 使用agg (aggregation)基于列的聚合操作，统计唯一值个数 item_id, cat_id, merchant_id, brand_id</span>
temp = groups[<span class="hljs-string">&#x27;item_id&#x27;</span>].agg([(<span class="hljs-string">&#x27;u2&#x27;</span>, <span class="hljs-string">&#x27;nunique&#x27;</span>)]).reset_index()
matrix = matrix.merge(temp, on=<span class="hljs-string">&#x27;user_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)

<span class="hljs-comment"># 时间间隔特征 u6 按照小时</span>
temp = groups[<span class="hljs-string">&#x27;time_stamp&#x27;</span>].agg([(<span class="hljs-string">&#x27;F_time&#x27;</span>, <span class="hljs-string">&#x27;min&#x27;</span>), (<span class="hljs-string">&#x27;L_time&#x27;</span>, <span class="hljs-string">&#x27;max&#x27;</span>)]).reset_index()
temp[<span class="hljs-string">&#x27;u6&#x27;</span>] = (temp[<span class="hljs-string">&#x27;L_time&#x27;</span>] - temp[<span class="hljs-string">&#x27;F_time&#x27;</span>]).dt.seconds/<span class="hljs-number">3600</span>
matrix = matrix.merge(temp[[<span class="hljs-string">&#x27;user_id&#x27;</span>, <span class="hljs-string">&#x27;u6&#x27;</span>]], on=<span class="hljs-string">&#x27;user_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)

<span class="hljs-comment"># 统计操作类型为0，1，2，3的个数</span>
temp = groups[<span class="hljs-string">&#x27;action_type&#x27;</span>].value_counts().unstack().reset_index().rename(columns=&#123;<span class="hljs-number">0</span>:<span class="hljs-string">&#x27;u7&#x27;</span>, <span class="hljs-number">1</span>:<span class="hljs-string">&#x27;u8&#x27;</span>, <span class="hljs-number">2</span>:<span class="hljs-string">&#x27;u9&#x27;</span>, <span class="hljs-number">3</span>:<span class="hljs-string">&#x27;u10&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=<span class="hljs-string">&#x27;user_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)

matrix.head(<span class="hljs-number">10</span>)

<span class="hljs-comment">#03</span>
<span class="hljs-comment"># 商家特征处理</span>
groups = user_log.groupby([<span class="hljs-string">&#x27;merchant_id&#x27;</span>])
<span class="hljs-comment"># 商家被交互行为数量 m1</span>
temp = groups.size().reset_index().rename(columns=&#123;<span class="hljs-number">0</span>:<span class="hljs-string">&#x27;m1&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=<span class="hljs-string">&#x27;merchant_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)
<span class="hljs-comment"># 统计商家被交互的user_id, item_id, cat_id, brand_id 唯一值</span>
temp = groups[<span class="hljs-string">&#x27;user_id&#x27;</span>, <span class="hljs-string">&#x27;item_id&#x27;</span>, <span class="hljs-string">&#x27;cat_id&#x27;</span>, <span class="hljs-string">&#x27;brand_id&#x27;</span>].nunique().reset_index(). rename(columns=&#123;<span class="hljs-string">&#x27;user_id&#x27;</span>:<span class="hljs-string">&#x27;m2&#x27;</span>, <span class="hljs-string">&#x27;item_id&#x27;</span>:<span class="hljs-string">&#x27;m3&#x27;</span>, <span class="hljs-string">&#x27;cat_id&#x27;</span>:<span class="hljs-string">&#x27;m4&#x27;</span>, <span class="hljs-string">&#x27;brand_id&#x27;</span>:<span class="hljs-string">&#x27;m5&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=<span class="hljs-string">&#x27;merchant_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)
<span class="hljs-comment"># 统计商家被交互的action_type 唯一值</span>
temp = groups[<span class="hljs-string">&#x27;action_type&#x27;</span>].value_counts().unstack(). reset_index().rename(columns=&#123;<span class="hljs-number">0</span>:<span class="hljs-string">&#x27;m6&#x27;</span>, <span class="hljs-number">1</span>:<span class="hljs-string">&#x27;m7&#x27;</span>, <span class="hljs-number">2</span>:<span class="hljs-string">&#x27;m8&#x27;</span>, <span class="hljs-number">3</span>:<span class="hljs-string">&#x27;m9&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=<span class="hljs-string">&#x27;merchant_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)

<span class="hljs-comment"># 按照merchant_id 统计随机负采样的个数</span>
temp = train_data[train_data[<span class="hljs-string">&#x27;label&#x27;</span>]==-<span class="hljs-number">1</span>]. groupby([<span class="hljs-string">&#x27;merchant_id&#x27;</span>]).size().reset_index().rename(columns=&#123;<span class="hljs-number">0</span>:<span class="hljs-string">&#x27;m10&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=<span class="hljs-string">&#x27;merchant_id&#x27;</span>, how=<span class="hljs-string">&#x27;left&#x27;</span>)

matrix.head(<span class="hljs-number">10</span>)

<span class="hljs-comment"># 04</span>
<span class="hljs-comment"># 不同用户不同商家特征处理</span>
groups = user_log.groupby(by=[<span class="hljs-string">&#x27;merchant_id&#x27;</span>,<span class="hljs-string">&#x27;user_id&#x27;</span>])
<span class="hljs-comment"># 交互行为数量 um1</span>
temp = groups.size().reset_index().rename(columns=&#123;<span class="hljs-number">0</span>:<span class="hljs-string">&#x27;um1&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=[<span class="hljs-string">&#x27;merchant_id&#x27;</span>,<span class="hljs-string">&#x27;user_id&#x27;</span>], how=<span class="hljs-string">&#x27;left&#x27;</span>)
<span class="hljs-comment"># 统计商家被交互的user_id, item_id, cat_id, brand_id 唯一值</span>
temp = groups[<span class="hljs-string">&#x27;item_id&#x27;</span>, <span class="hljs-string">&#x27;cat_id&#x27;</span>, <span class="hljs-string">&#x27;brand_id&#x27;</span>].nunique().reset_index(). rename(columns=&#123;<span class="hljs-string">&#x27;item_id&#x27;</span>:<span class="hljs-string">&#x27;um2&#x27;</span>, <span class="hljs-string">&#x27;cat_id&#x27;</span>:<span class="hljs-string">&#x27;um3&#x27;</span>, <span class="hljs-string">&#x27;brand_id&#x27;</span>:<span class="hljs-string">&#x27;um4&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=[<span class="hljs-string">&#x27;user_id&#x27;</span>,<span class="hljs-string">&#x27;merchant_id&#x27;</span>], how=<span class="hljs-string">&#x27;left&#x27;</span>)
<span class="hljs-comment"># 统计商家被交互的action_type 唯一值</span>
temp = groups[<span class="hljs-string">&#x27;action_type&#x27;</span>].value_counts().unstack(). reset_index().rename(columns=&#123;<span class="hljs-number">0</span>:<span class="hljs-string">&#x27;um5&#x27;</span>, <span class="hljs-number">1</span>:<span class="hljs-string">&#x27;um6&#x27;</span>, <span class="hljs-number">2</span>:<span class="hljs-string">&#x27;um7&#x27;</span>, <span class="hljs-number">3</span>:<span class="hljs-string">&#x27;um8&#x27;</span>&#125;)
matrix = matrix.merge(temp, on=[<span class="hljs-string">&#x27;user_id&#x27;</span>,<span class="hljs-string">&#x27;merchant_id&#x27;</span>], how=<span class="hljs-string">&#x27;left&#x27;</span>)

matrix.head(<span class="hljs-number">10</span>)

<span class="hljs-comment"># 05</span>
<span class="hljs-comment">#用户购买点击比</span>
matrix[<span class="hljs-string">&#x27;r1&#x27;</span>] = matrix[<span class="hljs-string">&#x27;u9&#x27;</span>]/matrix[<span class="hljs-string">&#x27;u7&#x27;</span>]
<span class="hljs-comment">#商家购买点击比</span>
matrix[<span class="hljs-string">&#x27;r2&#x27;</span>] = matrix[<span class="hljs-string">&#x27;m8&#x27;</span>]/matrix[<span class="hljs-string">&#x27;m6&#x27;</span>]
<span class="hljs-comment">#不同用户不同商家购买点击比</span>
matrix[<span class="hljs-string">&#x27;r3&#x27;</span>] = matrix[<span class="hljs-string">&#x27;um7&#x27;</span>]/matrix[<span class="hljs-string">&#x27;um5&#x27;</span>] 
matrix.fillna(<span class="hljs-number">0</span>, inplace=<span class="hljs-literal">True</span>)
<span class="hljs-comment"># # 修改age_range字段名称为 age_0, age_1, age_2... age_8</span>
temp = pd.get_dummies(matrix[<span class="hljs-string">&#x27;age_range&#x27;</span>], prefix=<span class="hljs-string">&#x27;age&#x27;</span>)
matrix = pd.concat([matrix, temp], axis=<span class="hljs-number">1</span>)
temp = pd.get_dummies(matrix[<span class="hljs-string">&#x27;gender&#x27;</span>], prefix=<span class="hljs-string">&#x27;g&#x27;</span>)
matrix = pd.concat([matrix, temp], axis=<span class="hljs-number">1</span>)

matrix.drop([<span class="hljs-string">&#x27;age_range&#x27;</span>, <span class="hljs-string">&#x27;gender&#x27;</span>], axis=<span class="hljs-number">1</span>, inplace=<span class="hljs-literal">True</span>)
matrix.head(<span class="hljs-number">10</span>)

<span class="hljs-comment"># 06 模型构建</span>
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split
<span class="hljs-keyword">import</span> xgboost <span class="hljs-keyword">as</span> xgb

train_y = matrix[matrix.origin == <span class="hljs-string">&quot;train&quot;</span>][<span class="hljs-string">&quot;label&quot;</span>]
train_X = matrix[matrix.origin == <span class="hljs-string">&quot;train&quot;</span>].iloc[:,<span class="hljs-number">4</span>:]
test_data = matrix[matrix.origin == <span class="hljs-string">&quot;test&quot;</span>].iloc[:,<span class="hljs-number">4</span>:]
<span class="hljs-comment"># 使用机器学习工具进行分析</span>
<span class="hljs-comment"># 将训练集进行切分，20%用于验证</span>
X_train, X_valid, y_train, y_valid = train_test_split(train_X, train_y, test_size=<span class="hljs-number">.2</span>)
<span class="hljs-comment"># 使用XGBoost</span>
model = xgb.XGBClassifier(
    max_depth=<span class="hljs-number">8</span>,
    n_estimators=<span class="hljs-number">1000</span>,
    min_child_weight=<span class="hljs-number">300</span>, 
    colsample_bytree=<span class="hljs-number">0.8</span>, 
    subsample=<span class="hljs-number">0.8</span>, 
    eta=<span class="hljs-number">0.3</span>,    
    seed=<span class="hljs-number">42</span>    
)

model.fit(
    X_train, y_train,
    eval_metric=<span class="hljs-string">&#x27;auc&#x27;</span>, eval_set=[(X_train, y_train), (X_valid, y_valid)],
    verbose=<span class="hljs-literal">True</span>,
    <span class="hljs-comment">#早停法，如果auc在10epoch没有进步就stop</span>
    early_stopping_rounds=<span class="hljs-number">10</span> 
)
model.fit(X_train, y_train)
prob = model.predict_proba(test_data)
submission[<span class="hljs-string">&#x27;prob&#x27;</span>] = pd.Series(prob[:,<span class="hljs-number">1</span>])
submission.drop([<span class="hljs-string">&#x27;origin&#x27;</span>], axis=<span class="hljs-number">1</span>, inplace=<span class="hljs-literal">True</span>)
submission.to_csv(<span class="hljs-string">&#x27;prediction.csv&#x27;</span>, index=<span class="hljs-literal">False</span>)</code></pre>
<br>
提交成绩：0.67 <br>

<h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ul>
<li><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/157550647">https://zhuanlan.zhihu.com/p/157550647</a></li>
<li><a target="_blank" rel="noopener" href="https://www.cnblogs.com/rossiXYZ/p/13911140.html">https://www.cnblogs.com/rossiXYZ/p/13911140.html</a></li>
<li><a target="_blank" rel="noopener" href="https://www.cnblogs.com/rossiXYZ/p/13796470.html">https://www.cnblogs.com/rossiXYZ/p/13796470.html</a></li>
<li><a target="_blank" rel="noopener" href="https://www.cnblogs.com/rossiXYZ/p/14331924.html">https://www.cnblogs.com/rossiXYZ/p/14331924.html</a></li>
<li><a target="_blank" rel="noopener" href="https://tech.sina.com.cn/roll/2020-07-01/doc-iircuyvk1399726.shtml">https://tech.sina.com.cn/roll/2020-07-01/doc-iircuyvk1399726.shtml</a></li>
</ul>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/walker_sue/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">机器学习</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/%E4%B8%AA%E6%80%A7%E5%8C%96%E6%8E%A8%E8%8D%90/">个性化推荐</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/BI/">BI</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">机器学习</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95/">推荐算法</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/walker_sue/2021/03/08/week6-RL/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">强化学习与推荐系统</span>
                        <span class="visible-mobile">Vorheriger</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/walker_sue/2021/02/14/BI-week4-airbnb/">
                        <span class="hidden-mobile">AIRBNB 个性化推荐与信用卡欺诈预测</span>
                        <span class="visible-mobile">Nächster</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;TOC</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">Suchen</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">Stichwort</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/walker_sue/js/debouncer.js" ></script>
<script  src="/walker_sue/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/walker_sue/js/lazyload.js" ></script>
  



  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/walker_sue/js/clipboard-use.js" ></script>







  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: '#post-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    function typing(id, title){
        var typed = new Typed('#' + id, {
            strings: [
              '  ',
              title + "&nbsp;",
            ],
            cursorChar: "_",
            typeSpeed: 70,
            loop: false,
        });
        typed.stop();
        $(document).ready(function () {
            $(".typed-cursor").addClass("h2");
            typed.start();
        });
    }
    
        typing("subtitle", "淘宝定向广告演化和天池天猫复购预测")
    
  </script>


  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/walker_sue/js/local-search.js" ></script>
  <script>
    var path = "/walker_sue/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>





  

  
    <!-- MathJax -->
    <script>
      MathJax = {
        tex: {
          inlineMath: [['$', '$'], ['\\(', '\\)']]
        },
        options: {
          renderActions: {
            findScript: [10, doc => {
              document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
                const display = !!node.type.match(/; *mode=display/);
                const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
                const text = document.createTextNode('');
                node.parentNode.replaceChild(text, node);
                math.start = { node: text, delim: '', n: 0 };
                math.end = { node: text, delim: '', n: 0 };
                doc.math.push(math);
              });
            }, '', false],
            insertedScript: [200, () => {
              document.querySelectorAll('mjx-container').forEach(node => {
                let target = node.parentNode;
                if (target.nodeName.toLowerCase() === 'li') {
                  target.parentNode.classList.add('has-jax');
                }
              });
            }, '', false]
          }
        }
      };
    </script>

    <script async src="https://cdn.staticfile.org/mathjax/3.0.5/es5/tex-svg.js" ></script>

  











</body>
</html>
